/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package co.edu.distribuidos.conectividad;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.jxta.discovery.DiscoveryService;
import net.jxta.document.Advertisement;
import net.jxta.document.AdvertisementFactory;
import net.jxta.id.ID;
import net.jxta.id.IDFactory;
import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.pipe.PipeID;
import net.jxta.pipe.PipeService;
import net.jxta.platform.NetworkManager;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.socket.JxtaServerSocket;
import net.jxta.socket.JxtaSocket;
import sun.awt.windows.ThemeReader;

/**
 *
 * @author alvar-go@uniandes.edu.co
 */
public class ServidorJXTA {


    public final static String SOCKET_ID = "urn:jxta:uuid-59616261646162614E5047205032503393B5C2F6CA7A41FBB0F890173088E79404";

    private final static String RUTA_CACHE = "./data/cache";

    private String nombreNodo;

    private NetworkManager manager;

    private JxtaServerSocket servidor;

    private DiscoveryService discovery;

    private ArrayList<Thread> conexiones;

    public ServidorJXTA(String nombreNodo) throws Exception{
        this.nombreNodo = nombreNodo;
        conexiones = new ArrayList<Thread>();
        manager = null;
        try {
            manager = new NetworkManager(NetworkManager.ConfigMode.ADHOC, nombreNodo, new File(RUTA_CACHE).toURI());
            manager.startNetwork();
            PeerGroup netPeerGroup = manager.getNetPeerGroup();
            PeerGroupID id = netPeerGroup.getPeerGroupID();
            PipeID idPipe = createNewPipeID(id);
            PipeAdvertisement pipeAdv = createPipeAdvertisement(idPipe);
            servidor = new JxtaServerSocket(netPeerGroup, pipeAdv);
            discovery = netPeerGroup.getDiscoveryService();


        } catch (Exception e) {
            throw new Exception("No fue posible contectar el nodo a la red.\n" + e.getMessage());
        }
    }

     private static PipeID createNewPipeID(PeerGroupID pgID) {
        PipeID socketID = null;

        try {
            socketID = (PipeID) IDFactory.fromURI(new URI(SOCKET_ID));
        } catch (Exception ex) {

        }
        return socketID;
    }

    private PipeAdvertisement createPipeAdvertisement(ID pipeId) {

        PipeAdvertisement advertisement = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(PipeAdvertisement.getAdvertisementType());

        advertisement.setPipeID(pipeId);
        advertisement.setType(PipeService.UnicastType);
        advertisement.setName("Pipe proyecto");
        return advertisement;
    }

    public void publicar(Advertisement adver)throws Exception{
        try {
            discovery.publish(adver);
        } catch (IOException ex) {
           throw new Exception("No se pudo realizar la publicación." + ex.getMessage());
        }
    }

    public void recibirConexiones(){
        while(true){
            try {
                JxtaSocket cliente = (JxtaSocket)servidor.accept();
                iniciarConexion(cliente);
            } catch (IOException ex) {
               ex.printStackTrace();
            }
        }
    }

    public void detenerJXTA(){
        manager.stopNetwork();
    }

    private synchronized void iniciarConexion(JxtaSocket cliente) {
        try {
            ThreadAtenderPeticion thread = new ThreadAtenderPeticion(cliente);
            conexiones.add(thread);
            thread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
